/*******************************************************************************
 *
 *	:  IO
 *
 *******************************************************************************/
#define PORT_PIN_CTEAT
#include "bsp.h"
#include "bsp_io.h"
#include "iohandle.h"
#include "pincfg.h"
#include "mytype.h"

/*******************************************************************************
 * @brief  ext sim io
 *******************************************************************************/
uint8_t ext_port_out[4][8];
uint8_t ext_port_in[4];

void bsp_pin_mux_cfg(gpio_type *gpio_x, uint32_t pin, gpio_mux_sel_type gpio_mux);

/*******************************************************************************
 * @brief  gpio cfg list
 *******************************************************************************/
static gpio_init_cfg_type gpio_cfg[] = {
	// LED
	{GPIOB, GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_0, 1, GPIO_PINS_3},
	{GPIOB, GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_0, 1, GPIO_PINS_4},

	// OLED SPI
	{GPIOE, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_4, 1, GPIO_PINS_13},
	{GPIOE, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_4, 1, GPIO_PINS_15},

	// U1
	{GPIOA, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, 1, GPIO_PINS_9},
	{GPIOA, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, 1, GPIO_PINS_10},
	// U3 / IIC
	//{GPIOD, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, 1, GPIO_PINS_8},
	//{GPIOD, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, 1, GPIO_PINS_9},
	{GPIOD, GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, 1, GPIO_PINS_8},
	{GPIOD, GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, 1, GPIO_PINS_9},
	// U7
	{GPIOC, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_8, 1, GPIO_PINS_0},
	{GPIOC, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_8, 1, GPIO_PINS_1},
	// U8
	{GPIOC, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_8, 1, GPIO_PINS_2},
	{GPIOC, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_8, 1, GPIO_PINS_3},
	// PWM
	{GPIOA, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_OPEN_DRAIN, GPIO_PULL_NONE, GPIO_MUX_2, 1, GPIO_PINS_6},
	// CAP
	{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_2, 1, GPIO_PINS_7},
	// QPI SS
	{GPIOB, GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_0, 1, GPIO_PINS_10},
	{GPIOB, GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_0, 1, GPIO_PINS_11},
	// QPI CLK IO
	{GPIOA, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_10, 1, GPIO_PINS_7},
	{GPIOC, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_10, 1, GPIO_PINS_4},
	{GPIOC, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_10, 1, GPIO_PINS_5},
	{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_10, 1, GPIO_PINS_0},
	{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_9, 1, GPIO_PINS_2},
	
	// I2S / SPI
	{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_UP, GPIO_MUX_5, 1, GPIO_PINS_13},
	{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_UP, GPIO_MUX_5, 1, GPIO_PINS_14},
	{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_UP, GPIO_MUX_5, 1, GPIO_PINS_15},
};

/*******************************************************************************
 * @brief  bsp_gpio_init
 * \param[in] us delay
 * \retval: none
 *******************************************************************************/
void bsp_gpio_init(void)
{
	int index;

	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOG_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOH_PERIPH_CLOCK, TRUE);

	/*gpio cfg*/
	for (index = 0; index < sizeof(gpio_cfg) / sizeof(gpio_init_cfg_type); index++)
	{
		gpio_init_type GPIO_InitStruct;

		GPIO_InitStruct.gpio_pins = gpio_cfg[index].pin;
		GPIO_InitStruct.gpio_mode = gpio_cfg[index].mode;
		GPIO_InitStruct.gpio_out_type = gpio_cfg[index].out_type;
		GPIO_InitStruct.gpio_pull = gpio_cfg[index].pull;
		GPIO_InitStruct.gpio_drive_strength = gpio_cfg[index].drive;

		gpio_init(gpio_cfg[index].port, &GPIO_InitStruct);

		if (gpio_cfg[index].mode == GPIO_MODE_MUX)
		{
			bsp_pin_mux_cfg(gpio_cfg[index].port, gpio_cfg[index].pin, gpio_cfg[index].mux);
		}

		if (gpio_cfg[index].mode == GPIO_MODE_OUTPUT)
		{
			if (gpio_cfg[index].val_init)
			{
				gpio_bits_set(gpio_cfg[index].port, gpio_cfg[index].pin);
			}
			else
			{
				gpio_bits_reset(gpio_cfg[index].port, gpio_cfg[index].pin);
			}
		}
	}

	o_led1.dis();
	o_led2.dis();

	u1_de.dir_out_pp();

	// flash
	nand_ss.dir_out_pp();
	snor_ss.dir_out_pp();
	nand_ss.en();
	snor_ss.en();

	// oled pin
	oled_cs.dir_out_pp();
	oled_dc.dir_out_pp();
	oled_rst.dir_out_pp();
	oled_cs.en();
	oled_rst.dis();

	// sd cd
	sd_cd.dir_in_up();

	// key
	key1.dir_in_up();
	key2.dir_in_up();
	key3.dir_in_up();
	key4.dir_in_up();

	esp_rst.dir_out_pp();
	esp_rst.dis();
}

/*******************************************************************************
 * @brief  bsp_gpio
 * \param[in] us delay
 * \retval: none
 *******************************************************************************/
void bsp_pin_mux_cfg(gpio_type *gpio_x, uint32_t pin, gpio_mux_sel_type gpio_mux)
{
	loop(16)
	{
		if ((1UL << index) & pin)
		{
			gpio_pin_mux_config(gpio_x, (gpio_pins_source_type)index, gpio_mux);
		}
	}
}

/*******************************************************************************
 * @brief  bsp_gpio
 * \param[in] us delay
 * \retval: none
 *******************************************************************************/
void bsp_gpio_mode_out_pp(gpio_type *port, uint8_t pin)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 1UL);
	group_bits1_set(port->omode, pin, 0UL);
	group_bits2_set(port->odrvr, pin, 1UL);

	intx_enable();
}

void bsp_gpio_mode_out_od(gpio_type *port, uint8_t pin)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 1UL);
	group_bits1_set(port->omode, pin, 1UL);
	group_bits2_set(port->odrvr, pin, 1UL);

	intx_enable();
}

void bsp_gpio_mode_out_pp_spd(gpio_type *port, uint8_t pin, uint32_t spd)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 1UL);
	group_bits1_set(port->omode, pin, 0UL);
	group_bits2_set(port->odrvr, pin, spd);

	intx_enable();
}

void bsp_gpio_mode_out_od_spd(gpio_type *port, uint8_t pin, uint32_t spd)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 1UL);
	group_bits1_set(port->omode, pin, 1UL);
	group_bits2_set(port->odrvr, pin, spd);

	intx_enable();
}

void bsp_gpio_mode_in_up(gpio_type *port, uint8_t pin)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 0UL);
	group_bits2_set(port->pull, pin, 1UL);

	intx_enable();
}

void bsp_gpio_mode_in_dn(gpio_type *port, uint8_t pin)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 0UL);
	group_bits2_set(port->pull, pin, 2UL);

	intx_enable();
}

void bsp_gpio_mode_in_ft(gpio_type *port, uint8_t pin)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 0UL);
	group_bits2_set(port->pull, pin, 0UL);

	intx_enable();
}

void bsp_gpio_mode_ain(gpio_type *port, uint8_t pin)
{
	intx_alloc();

	intx_disable();

	group_bits2_set(port->cfgr, pin, 3UL);
	group_bits2_set(port->pull, pin, 0UL);

	intx_enable();
}

void bsp_gpio_mode_set(gpio_type *port, uint8_t pin, char pm)
{
	switch (pm)
	{
	case PIN_MODE_IN_UP:
	{
		bsp_gpio_mode_in_up(port, pin);
		break;
	}
	case PIN_MODE_IN_DN:
	{
		bsp_gpio_mode_in_dn(port, pin);
		break;
	}
	case PIN_MODE_IN_FLOAT:
	{
		bsp_gpio_mode_in_ft(port, pin);
		break;
	}
	case PIN_MODE_IN_AIN:
	{
		bsp_gpio_mode_ain(port, pin);
		break;
	};
	case PIN_MODE_OUT_SL_PP:
	{
		bsp_gpio_mode_out_pp_spd(port, pin, 2);
		break;
	}
	case PIN_MODE_OUT_SL_OD:
	{
		bsp_gpio_mode_out_od_spd(port, pin, 2);
		break;
	}
	case PIN_MODE_OUT_SM_PP:
	{
		bsp_gpio_mode_out_pp_spd(port, pin, 2);
		break;
	}
	case PIN_MODE_OUT_SM_OD:
	{
		bsp_gpio_mode_out_od_spd(port, pin, 2);
		break;
	}
	case PIN_MODE_OUT_SH_PP:
	{
		bsp_gpio_mode_out_pp_spd(port, pin, 1);
		break;
	}
	case PIN_MODE_OUT_SH_OD:
	{
		bsp_gpio_mode_out_od_spd(port, pin, 1);
		break;
	}
	default:
	{
		break;
	}
	}
}

/*******************************************************************************
 * @brief  ext sim io
 *******************************************************************************/
uint8_t ext_io_out_get(char gp)
{
	uint8_t val = 0;

#define EXT_IO_OUT_BIT(n)    \
	if (ext_port_out[gp][n]) \
		val |= _BIT(n);

	EXT_IO_OUT_BIT(0);
	EXT_IO_OUT_BIT(1);
	EXT_IO_OUT_BIT(2);
	EXT_IO_OUT_BIT(3);
	EXT_IO_OUT_BIT(4);
	EXT_IO_OUT_BIT(5);
	EXT_IO_OUT_BIT(6);
	EXT_IO_OUT_BIT(7);

	return val;
}
